export = {};

import * as React from "react";

// const Layout: React.FunctionComponent & { Header: React.FunctionComponent; } = () => {
//   return (
//     <div></div>
//   );
// };
// Layout.Header = () => {
//   return (
//     <div>hi</div>
//   );
// };
//↑的类型太长了,我们可以为它取个别名
type Layout = React.FunctionComponent & { Header: React.FunctionComponent; };

const Layout: Layout = () => {
  return (
    <div></div>
  );
};

Layout.Header = () => {
  return (
    <div>hi</div>
  );
};

/** type和interface很像,那么该怎么选用呢?*/
// type是给一个已知的类型取了一个别名
// interface是声明了一个新的类型

/** 类型别名会给一个类型起个新名字。
  类型别名有时和接口很像，但是可以作用于原始值，联合类型，元组以及其它任何你需要手写的类型。
  给原始类型起别名通常没什么用，尽管可以做为文档的一种形式使用。*/
type Name = string;
const name: string = 'ahhh';
const name2: Name = 'ahhh2'; // 更语义化一点
type Age = number; // 让写代码的人更爽一点


/** 同接口一样，类型别名也可以是泛型 - 我们可以添加类型参数并且在别名声明的右侧传入：*/
type Container<T> = { value: T };


/** 我们也可以使用类型别名来在属性里引用自己：*/
type Tree<T> = {
  value: T;
  left: Tree<T>;
  right: Tree<T>;
}


/** 与交叉类型一起使用，我们可以创建出一些十分稀奇古怪的类型。*/
type LinkedList<T> = T & { next: LinkedList<T> };

interface Person {
  name: string;
}

var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;


/** 然而，类型别名不能出现在声明右侧的任何地方。*/
type Yikes = Array<Yikes>; // error //TODO 么有报错
let x: Yikes;



type Alias = { num: number }
interface Interface {
  num: number;
}
declare function aliased(arg: Alias): Alias;
declare function interfaced(arg: Interface): Interface;
